﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SocketHelper.Helper;
using System.Threading;
using System.IO;
using SocketHelper.Models;
using TouchSocket;
using TouchSocket.Sockets;
using TouchSocket.Core;
using Masuit;
using Masuit.Tools;


namespace SocketHelper
{
    public partial class SocketFormMain : DevExpress.XtraEditors.XtraForm
    {
        //通信开启状态
        private bool _isOpen = false;
        //循环发送信息状态
        private volatile bool _isCycle = false;
        //循环发送消息线程
        Thread CycleSendThread;
        //发送按钮状态
        private volatile bool _isSending = false;
        //日志路径
        private string logFilePath = "";
        //tcp服务端
        private TcpService tcpService = new TcpService();
        //tcp服务端id(目前只允许连接一个客户端)
        private string tcpClientId = "";
        //tcp客户端
        private TcpClient tcpClient = new TcpClient();
        //udp客户端
        private UdpSession udpClient = new UdpSession();
        public SocketFormMain()
        {
            InitializeComponent();
            InitData();
            InitSaveLog();
        }
        //初始化数据
        private void InitData()
        {
            comboBoxEditType.Properties.Items.AddRange(Faker.GetCommunicationType());
            comboBoxEditIp.Properties.Items.AddRange(Faker.GetIps());

            //设置默认显示
            comboBoxEditType.SelectedIndex = 0;
            comboBoxEditIp.SelectedIndex = 0;

        }
        private void InitSaveLog()
        {
            var LogThread = new Thread(() =>
            {
                while (true)
                {
                    if (checkEditRec2File.Checked && !string.IsNullOrEmpty(logFilePath))
                    {
                        File.WriteAllText(logFilePath, memoEditLog.Text);
                    }

                    Thread.Sleep(10000);
                }
            });
            LogThread.Start();
        }

        //打开/关闭 Tcp Client/Server,Udp
        //todo: 点击打开通信连接
        private void simpleButton1_Click(object sender, EventArgs e)
        {

            try
            {
                if (comboBoxEditType.Text == CommunicationType.TcpServer.ToString())
                {
                    StartTcpServer();

                }
                else if (comboBoxEditType.Text == CommunicationType.TcpClient.ToString())
                {
                    StartTcpClient();
                }
                else
                {
                    //udp
                    StartUdpServer();
                }
            }
            catch (Exception ex)
            {
                btnOpen.Text = "打开";
                memoEditLog.AppendText(ex.Message.FormatStringLog());
            }
        }
        //打开udp客户端
        private void StartUdpServer()
        {
            if (_isOpen)
            {
                udpClient.Stop();
                _isOpen = false;
                btnOpen.Text = "打开";
                ChangeComboxEnable(true);
                memoEditLog.AppendText("udp客户端关闭".FormatStringLog());
            }
            else
            {
                var ip = comboBoxEditIp.Text;
                var port = textEditPort.Text.ToInt32();

                udpClient.Setup(new TouchSocketConfig()
                    .SetBindIPHost(new IPHost(8080))
                    .SetRemoteIPHost($"{ip}:{port}"));
                
                udpClient.Received = (IUdpSession client, UdpReceivedDataEventArgs e) =>
                {

                    var msg = e.ByteBlock.ToString();
                    Invoke(new Action(() =>
                    {
                        if (checkEditRecAscii.Checked)
                        {
                            Invoke(new Action(() =>
                            {
                                memoEditLog.AppendText($"已从服务端接收到信息：{msg}".FormatStringLog());
                            }));
                        }
                        else
                        {
                            Invoke(new Action(() =>
                            {
                                memoEditLog.AppendText($@"已从服务端接收到信息：{string.Join(" ", e.ByteBlock.GetMemory().ToArray().Take(e.ByteBlock.Length).Select(b => b.ToString("X2")).ToArray())}"
                                    .FormatStringLog());
                            }));
                        }
                    }));
                    return EasyTask.CompletedTask;
                };

                udpClient.Start();
                udpClient.Send("客户端连接成功！");
                memoEditLog.AppendText("udp客户端连接".FormatStringLog());
                btnOpen.Text = "关闭";
                ChangeComboxEnable(false);
                _isOpen = true;
            }
            
        }
        //打开TcpClient客户端
        private void StartTcpClient()
        {
            if (_isOpen)
            {
                tcpClient.Close();
                _isOpen = false;
                btnOpen.Text = "打开";
                ChangeComboxEnable(true);
                memoEditLog.AppendText("tcp客户端关闭".FormatStringLog());
            }
            else
            {
                //即将连接到服务器，此时已经创建socket，但是还未建立tcp
                tcpClient.Connecting = (client, e) =>
                {
                    Invoke(new Action(() =>
                    {
                        memoEditLog.AppendText($"{client.IP}:{client.Port} 正在连接服务器".FormatStringLog());
                    }));
                    return EasyTask.CompletedTask;
                };
                //成功连接到服务器
                tcpClient.Connected = (client, e) =>
                {
                    Invoke(new Action(() =>
                    {
                        memoEditLog.AppendText($"{client.IP}:{client.Port} 客户端连接成功".FormatStringLog());
                    }));
                   
                    return EasyTask.CompletedTask;
                };
                //即将从服务器断开连接。此处仅主动断开才有效。
                tcpClient.Closing = (client, e) =>
                {
                    Invoke(new Action(() =>
                    {
                        memoEditLog.AppendText($"{client.IP}:{client.Port} 客户端正在断开连接".FormatStringLog());
                    }));
                    return EasyTask.CompletedTask;
                };
                //从服务器断开连接，当连接不成功时不会触发。
                tcpClient.Closed = (client, e) =>
                {
                    Invoke(new Action(() =>
                    {
                        memoEditLog.AppendText($"{client.IP}:{client.Port} 客户端断开连接".FormatStringLog());
                    }));
                    return EasyTask.CompletedTask;
                };

                tcpClient.Received = (client, e) =>
                {
                    //从服务器收到信息。但是一般byteBlock和requestInfo会根据适配器呈现不同的值。
                    var mes = e.ByteBlock.Span.ToString(Encoding.UTF8);
                    tcpClient.Logger.Info($"客户端接收到信息：{mes}");
                    if (checkEditRecAscii.Checked)
                    {
                        Invoke(new Action(() =>
                        {
                            memoEditLog.AppendText($"已从{client.IP}:{client.Port}接收到信息：{mes}".FormatStringLog());
                        }));
                    }
                    else
                    {
                        Invoke(new Action(() =>
                        {
                            memoEditLog.AppendText($@"已从{client.IP}:{client.Port}接收到信息：{string.Join(" ", e.ByteBlock.GetMemory().ToArray().Take(e.ByteBlock.Length).Select(b => b.ToString("X2")).ToArray())}"
                                .FormatStringLog());
                        }));
                    }
                    //收到的信息返回给客户端
                    client.Send($"客户端收到信息: {mes}");
                    return EasyTask.CompletedTask;
                };


                var ip = comboBoxEditIp.Text;
                var port = textEditPort.Text.ToInt32();


                //载入配置
                tcpClient.Setup(new TouchSocketConfig()
                      .SetRemoteIPHost(ip + ":" + port));

                tcpClient.Connect();//调用连接，当连接不成功时，会抛出异常。
                tcpClient.Send("客户端请求连接！！！");
                _isOpen = true;

                ChangeComboxEnable(false);
                btnOpen.Text = "关闭";
                memoEditLog.AppendText("连接打开".FormatStringLog());


            }
        }
        //打开TcpServer服务端
        private void StartTcpServer()
        {
            if (_isOpen)
            {
                tcpService.Stop();
                _isOpen = false;
                btnOpen.Text = "打开";
                ChangeComboxEnable(true);
                memoEditLog.AppendText("tcp服务端关闭".FormatStringLog());
            }
            else
            {
                //有客户端正在连接
                tcpService.Connecting = (client, e) =>
                {
                    Invoke(new Action(() =>
                    {
                        memoEditLog.AppendText($"正在连接{client.IP}:{client.Port} 客户端".FormatStringLog());
                    }));
                    return EasyTask.CompletedTask;
                };
                //有客户端成功连接
                tcpService.Connected = (client, args) =>
                {
                    Invoke(new Action(() =>
                    {
                        memoEditLog.AppendText($"{client.IP}:{client.Port} 客户端连接成功".FormatStringLog());
                    }));
                    tcpClientId = client.Id;
                    return EasyTask.CompletedTask;
                };
                //有客户端正在断开连接，只有当主动断开时才有效。
                tcpService.Closing = (client, e) =>
                {
                    Invoke(new Action(() =>
                    {
                        memoEditLog.AppendText($"{client.IP}:{client.Port} 客户端正在断开连接".FormatStringLog());
                    }));
                    return EasyTask.CompletedTask;
                };
                //有客户端断开连接
                tcpService.Closed = (client, e) =>
                {
                    Invoke(new Action(() =>
                    {
                        tcpClientId = "";
                        memoEditLog.AppendText($"{client.IP}:{client.Port} 客户端断开连接".FormatStringLog());
                    }));
                    return EasyTask.CompletedTask;
                };
                //从客户端收到信息
                tcpService.Received = async (client, e) =>
                {
                    var mes = e.ByteBlock.Span.ToString(Encoding.UTF8);
                    client.Logger.Info($"已从{client.Id}:{client.Port}接收到信息：{mes}");
                    if (checkEditRecAscii.Checked)
                    {
                        //如果按照ascii类型接收
                        Invoke(new Action(() =>
                        {
                            memoEditLog.AppendText($"已从{client.IP}:{client.Port}接收到信息：{mes}".FormatStringLog());
                        }));

                    }
                    else
                    {
                        //按照16进制接收
                        Invoke(new Action(() =>
                        {
                            memoEditLog.AppendText($@"已从{client.IP}:{client.Port}接收到信息：{string.Join(" ", e.ByteBlock.GetMemory().ToArray().Take(e.ByteBlock.Length).Select(b => b.ToString("X2")).ToArray())}"
                                .FormatStringLog());
                        }));

                    }
                };
                var ip = comboBoxEditIp.Text;
                var port = textEditPort.Text.ToInt32();


                tcpService.Setup(new TouchSocketConfig()//载入配置
                    .SetListenOptions(option =>
                    {
                        option.Add(new TcpListenOption()
                        {
                            IpHost = ip + ":" + port,
                            Name = "server1",//名称用于区分监听
                            ServiceSslOption = null,//可以针对当前监听，单独启用ssl加密
                            Adapter = () => new NormalDataHandlingAdapter(),//可以单独对当前地址监听，配置适配器
                                                                            //还有其他可配置项，都是单独对当前地址有效。
                        });
                    }));

                tcpService.Start();//启动
                _isOpen = true;
                ChangeComboxEnable(false);
                btnOpen.Text = "关闭";
                memoEditLog.AppendText("tcp客户端打开".FormatStringLog());
            }

            ChangeMemoEditLastend();


        }
        //自动滚屏
        private void ChangeMemoEditLastend()
        {
            if (checkEditAuto.Checked)
            {
                memoEditLog.SelectionStart = memoEditLog.Text.Length;
                memoEditLog.ScrollToCaret();
            }
        }

        //打开/关闭后不能/可以设置通信参数
        public void ChangeComboxEnable(bool enable)
        {
            comboBoxEditType.Enabled = enable;
            comboBoxEditIp.Enabled = enable;
            textEditPort.Enabled = enable;
        }

        //发送/停止发送后不能/可以设置发送参数

        private void DisableControls(bool enable)
        {
            checkEditSendAscii.Enabled = enable;
            checkEditSendHex.Enabled = enable;
            checkEditCycle.Enabled = enable;
            textEditCycle.Enabled = enable;
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            memoEditLog.Text = "";
        }
        //todo: 发送数据
        private void SendMessageFromService(string result)
        {
            Invoke(new Action(() =>
            {
                if (checkEditSendAscii.Checked)
                {
                    memoEditLog.AppendText(result.FormatStringLog());

                    if (comboBoxEditType.Text == CommunicationType.TcpServer.ToString())
                    {
                        tcpService.GetClient(tcpClientId).Send(result);
                    }
                    else if (comboBoxEditType.Text == CommunicationType.TcpClient.ToString())
                    {
                        tcpClient.Send(result);
                    }
                    else
                    {
                        udpClient.Send(result);

                    }
                }
                else
                {
                    byte[] sendBytes = TranStrToToHexByte(result);

                    if (sendBytes != null)
                    {
                        memoEditLog.AppendText(string.Join(" ", sendBytes.Select(b => b.ToString("X2")).ToArray()).FormatStringLog());

                        if (comboBoxEditType.Text == CommunicationType.TcpServer.ToString())
                        {
                            //tcpService.GetClients().ToList().ForEach(client => client.Send(sendBytes, 0, sendBytes.Length));
                            tcpService.GetClient(tcpClientId).Send(sendBytes);

                        }
                        else if (comboBoxEditType.Text == CommunicationType.TcpClient.ToString())
                        {
                            tcpClient.Send(sendBytes);
                        }
                        else
                        {
                            udpClient.Send(sendBytes);
                        }
                    }
                }
            }));
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            string result = memoEditSend.Text;
            //首先判断是否有追加随机数
            if (checkEditRandom.Checked)
            {
                result += new Random().Next(1, 999).ToString();
            }
            if (result.Length <= 0)
            {
                return;
            }
            try
            {
                //勾选循环发送信息
                if (checkEditCycle.Checked)
                {
                    //且正在发送中,中止线程
                    if (_isSending && _isCycle)
                    {
                        CycleSendThread.Abort();
                        _isCycle = false;
                        _isSending = false;
                        btnSend.Text = "发送";
                        ChangeComboxEnable(true);

                    }
                    else
                    {
                        //实例化循环发送线程
                        CycleSendThread = new Thread(() =>
                        {
                            while (_isCycle)
                            {
                                SendMessageFromService(result);
                                Thread.Sleep(textEditCycle.EditValue.ToString().ToInt32());
                            }
                        });
                        CycleSendThread.Start();
                        _isCycle = true;
                        //禁用发送参数设置
                        ChangeComboxEnable(false);
                        btnSend.Text = "停止发送";
                        _isSending = true;
                    }


                }
                else
                {
                    //未勾选循环发送消息
                    SendMessageFromService(result);
                    //禁用发送参数设置
                    ChangeComboxEnable(false);
                    _isSending = true;
                }

            }
            catch (Exception ex)
            {
                memoEditLog.AppendText(ex.Message.FormatStringLog());
            }
        }

        //字符串转16进制
        private byte[] TranStrToToHexByte(string hexString)
        {
            int i;
            hexString = hexString.Replace(" ", "");//清除空格
            if ((hexString.Length % 2) != 0)//奇数个
            {
                byte[] returnBytes = new byte[(hexString.Length + 1) / 2];

                try
                {
                    for (i = 0; i < (hexString.Length - 1) / 2; i++)
                    {
                        returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                    }
                    returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16);
                }
                catch
                {
                    memoEditLog.AppendText("含有非16进制字符".FormatStringLog());
                    return null;
                }

                return returnBytes;
            }
            else
            {
                byte[] returnBytes = new byte[(hexString.Length) / 2];
                try
                {
                    for (i = 0; i < returnBytes.Length; i++)
                    {
                        returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                    }
                }
                catch
                {
                    memoEditLog.AppendText("含有非16进制字符".FormatStringLog());
                    return null;
                }
                return returnBytes;
            }
        }
        //以日志形式显示
        private void checkEditRecLog_CheckedChanged(object sender, EventArgs e)
        {
            //StringExtension.checkEditRecLog = checkEditRecLog.Checked;
        }

        private void checkEditRec2File_CheckedChanged(object sender, EventArgs e)
        {
            if (checkEditRec2File.Checked)
            {
                // 弹出保存文件对话框
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    logFilePath = saveFileDialog.FileName;
                }
            }
        }
    }
}
